iT邦幫忙

2024 iThome 鐵人賽

DAY 8
1

在 Rust 中,結構體(struct)和元組(tuple)是定義自訂類別的重要工具。它們讓開發者能夠清晰地組織和管理資料,並在程式中表達不同的數據結構。本篇文章將介紹如何在 Rust 中運用結構體與元組來定義自訂類別,並將其與 Python 中的類似結構進行比較,幫助開發者快速理解並運用這些概念。


一、元組:簡單且靈活的多值組合

元組是一種輕量的資料結構,可以用來存放多個不同類別的值。Rust 和 Python 的元組都具有這種特性,但它們在某些細節上略有不同。

1. Rust 的元組

Rust 的元組能夠容納多種類型的值,你可以使用索引來存取元組中的元素。這讓元組非常適合用來存放臨時且不需要命名的數據。

fn main() {
    let person: (&str, i32) = ("Alice", 30); // 定義一個元組,包含名字和年齡
    println!("名字:{},年齡:{}", person.0, person.1); // 使用索引存取元組中的元素
}
  • 優點:快速存放多個不同類別的值,簡單易用。
  • 缺點:需使用索引存取,對於大型數據結構可讀性較低。

2. Python 的元組

Python 的元組與 Rust 類似,可以存放多個不同類別的值,但它們是不可變的(immutable)。這意味著一旦建立後,元組中的值就無法改變。

person = ("Alice", 30)
print(f"名字:{person[0]},年齡:{person[1]}")
  • 優點:簡單易用,適合用於臨時數據存放,且不可變性增加了數據的穩定性。
  • 缺點:值不可改變,無法對元組的內容進行修改。

Rust 與 Python 的元組比較

特性 Rust 元組 Python 元組
可變性 可變(如用 mut 不可變
存取方式 使用索引(如 person.0 使用索引(如 person[0]
適用場景 臨時存放多類別數據 短期、臨時數據儲存

二、結構體:有結構的自訂類別

結構體比元組更強大,適合用來表示相關性強的數據,並且可以為每個欄位賦予名稱,使程式碼更具可讀性。

1. Rust 的結構體定義

Rust 的結構體允許你定義每個欄位的名稱和類別。這種設計使得結構體在存取和操作時非常直觀。

struct Person {
    name: String,
    age: u8,
}

fn main() {
    let alice = Person {
        name: String::from("Alice"),
        age: 30,
    };

    println!("名字:{},年齡:{}", alice.name, alice.age);
}
  • 優點:欄位有名稱,增加了程式碼的可讀性和可維護性。
  • 缺點:定義較為繁瑣,特別是對於簡單的數據結構。

2. Python 的類別

Python 沒有結構體,但類別(class)可以實現類似的功能。類別不僅允許定義屬性,還可以包含方法,這讓它非常適合大型專案的開發。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

alice = Person("Alice", 30)
print(f"名字:{alice.name},年齡:{alice.age}")
  • 優點:支援物件導向設計,能夠包含方法,靈活多變。
  • 缺點:語法稍為複雜,需要定義建構子和方法。

Rust 與 Python 的結構體和類別比較

特性 Rust 結構體 Python 類別
定義方式 struct 關鍵字 class 關鍵字
存取方式 使用欄位名稱 使用屬性名稱
是否支援方法 支援(使用 impl 區塊) 支援
適用場景 數據模型的定義與管理 對象導向程式設計

三、元組結構體:結構體與元組的結合

Rust 提供了一種介於結構體和元組之間的資料結構,稱為元組結構體。元組結構體擁有結構體的自訂類別特性,但其欄位沒有名稱。

1. 元組結構體

元組結構體適合在不需要欄位名稱時使用,它保留了結構體的類別優勢,同時保持了元組的簡潔性。

struct Color(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    println!("黑色的 RGB 值:({}, {}, {})", black.0, black.1, black.2);
}
  • 優點:簡單且快速,適合用於封裝小型數據。
  • 缺點:缺少欄位名稱,在使用上不夠直觀。

元組結構體 vs 普通結構體

特性 元組結構體 普通結構體
欄位命名 有,使用明確的名稱
存取方式 使用索引(如 black.0 使用欄位名稱(如 person.name
適用情境 簡單封裝數據 需要清晰表達數據的情境

四、結構體中的方法定義

在 Rust 中,結構體可以擁有方法,使得結構體不僅僅是靜態的資料結構,也能帶有行為。這種設計讓 Rust 的結構體更具實用性。

Rust 的方法定義

以下範例展示如何為 Person 結構體定義方法,讓結構體具備自我介紹的功能。

struct Person {
    name: String,
    age: u8,
}

impl Person {
    fn greet(&self) {
        println!("你好,我是 {},我 {} 歲", self.name, self.age);
    }
}

fn main() {
    let bob = Person {
        name: String::from("Bob"),
        age: 25,
    };
    bob.greet(); // 呼叫方法
}
  • 優點:結構體能夠擁有行為,類似於物件導向設計。
  • 注意&self 用來表示對結構體的不可變引用,無法修改結構體內部的資料。

五、結構體的所有權與借用

Rust 的所有權和借用機制是其核心特性之一,這些機制在使用結構體時尤其重要。當我們將結構體實例傳遞給其他函數或方法時,可能會發生所有權的轉移或借用。

借用結構體

借用是避免所有權轉移的方法之一,這樣可以使用結構體而不改變其擁有者。

fn show_person(person: &Person) {
    println!("名字:{},年齡:{}", person.name, person.age);
}

fn main() {
    let alice = Person {
        name: String::from("Alice"),
        age: 30,
    };
    show_person(&alice);  // 借用 alice,而不是轉移所有權
}
  • 優點:節省記憶體,避免不必要的複製。
  • 注意:借用有不可變借用(&)和可變借用(&mut),需根據情境選擇。

六、結構體的進階應用

:特性(Trait)和泛型結構體

1. 使用 derive 為結構體添加特性

Rust 的結構體可以自動衍生(derive)許多常用的特性,如 DebugClonePartialEq,這樣的設計大幅提高了結構體的便利性。

#[derive(Debug, Clone, PartialEq)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point1 = Point { x: 5, y: 10 };
    let point2 = point1.clone();
    println!("{:?}", point1); 
    println!("點相等嗎?{}", point1 == point2);
}

2. 泛型結構體

泛型結構體允許在定義時不限制數據的類別,增加了結構體的彈性和重用性。

struct GenericPoint<T> {
    x: T,
    y: T,
}

fn main() {
    let integer_point = GenericPoint { x: 5, y: 10 };
    let float_point = GenericPoint { x: 1.2, y: 3.4 };
    println!("整數點: ({}, {}), 浮點數點: ({}, {})", integer_point.x, integer_point.y, float_point.x, float_point.y);
}

七、總結

在這篇文章中,我們深入了解了 Rust 中的結構體與元組,並展示了它們如何幫助開發者清晰地組織和管理資料。以下是主要重點:

  • 元組:適合快速存放多類型資料,不需要命名欄位。
  • 結構體:增加了欄位名稱的清晰度,適合更複雜的資料模型。
  • 元組結構體:結合了結構體和元組的優點,適合簡單封裝數據。
  • 方法:為結構體添加行為,使其更具功能性。
  • 特性與泛型:提升結構體的靈活性,適應多樣化的開發需求。

透過掌握這些工具,你將能在 Rust 中更高效地組織和管理程式中的資料,撰寫出結構清晰、易於維護的程式碼。


上一篇
[Day 7] 函數與方法定義:如何在 Rust 中設計函數
下一篇
[Day 9] Rust 中的枚舉:代碼範例與應用
系列文
從 Python 開發者的角度學習 Rust —— 從語法基礎到實戰應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言